import { v4 as uuidv4 } from 'uuid';
import {
  BATTLE_SKILL_ATTRIBUTE,
  NORMAL_ATTACK,
  type BattleSkillAttribute,
  type BattleSkillAttributeKey,
} from '../../data/battle-skill';
import { CharacterAttributes } from '../attributes/character-attributes';
import { ATTRIBUTE_TYPE, type Attribute } from '../attributes/type';
import { type BattleSkill } from '../battle-skill';
import { BattleSkillFactory } from '../battle-skill/factory';
import type { Enemy } from '../enemy';
import type { Teammate } from '../teammate';

/**
 * 战斗阵营枚举
 */
export const BATTLE_SIDE = {
  /** 玩家阵营 */
  PLAYER: 'PLAYER',
  /** 敌人阵营 */
  ENEMY: 'ENEMY',
} as const;

export type BattleSide = (typeof BATTLE_SIDE)[keyof typeof BATTLE_SIDE];

/**
 * 战斗单位类
 * 代表参与战斗的单个角色，包含属性、状态和战斗行为
 */
export class BattleUnit {
  id: string;
  rawId: string;
  name: string;
  side: BattleSide;
  attributes: CharacterAttributes;
  currentHealth: number;
  isActive: boolean = true;
  lastDamageSource: BattleUnit | null = null;
  lastDamageTaken: {
    amount: number;
    source: BattleUnit | null;
    timestamp: number;
    wasLethal: boolean;
    previousHealth: number;
    currentHealth: number;
    healthLost: number;
    skill: BattleSkill | null;
  } | null = null;
  battleSkillAttributes: BattleSkillAttribute;
  /** 单位拥有的技能列表 */
  readonly skills: BattleSkill[] = [
    BattleSkillFactory.createBattleSkillByConfig(NORMAL_ATTACK),
  ];

  /**
   * 创建战斗单位
   * @param id - 单位唯一标识
   * @param name - 单位名称
   * @param side - 所属阵营
   * @param attributes - 单位属性配置
   * @param skills - 单位技能列表（可选，默包含普通攻击）
   */
  constructor(
    id: string,
    rawId: string,
    name: string,
    side: BattleSide,
    attributes: Attribute,
    skills?: BattleSkill[]
  ) {
    this.id = id;
    this.rawId = rawId;
    this.name = name;
    this.side = side;
    this.attributes = new CharacterAttributes(attributes);
    this.currentHealth = this.maxHealth;
    this.battleSkillAttributes = {
      [BATTLE_SKILL_ATTRIBUTE.ATTACK]: this.attributes.getAttributeValue(
        ATTRIBUTE_TYPE.ATTACK
      ),
      [BATTLE_SKILL_ATTRIBUTE.DEFENSE]: this.attributes.getAttributeValue(
        ATTRIBUTE_TYPE.DEFENSE
      ),
      [BATTLE_SKILL_ATTRIBUTE.SPEED]: this.attributes.getAttributeValue(
        ATTRIBUTE_TYPE.SPEED
      ),
      [BATTLE_SKILL_ATTRIBUTE.MAX_HEALTH]: this.attributes.getAttributeValue(
        ATTRIBUTE_TYPE.HEALTH
      ),
      [BATTLE_SKILL_ATTRIBUTE.CURRENT_HEALTH]: this.currentHealth,
    };

    if (skills) {
      this.skills = [
        BattleSkillFactory.createBattleSkillByConfig(NORMAL_ATTACK),
        ...skills,
      ];
    }
  }

  /** 获取最大生命值 */
  get maxHealth(): number {
    return this.attributes.getAttributeValue(ATTRIBUTE_TYPE.HEALTH);
  }

  /** 获取攻击力 */
  get attack(): number {
    return this.attributes.getAttributeValue(ATTRIBUTE_TYPE.ATTACK);
  }

  /** 获取防御力 */
  get defense(): number {
    return this.attributes.getAttributeValue(ATTRIBUTE_TYPE.DEFENSE);
  }

  /** 获取速度 */
  get speed(): number {
    return this.attributes.getAttributeValue(ATTRIBUTE_TYPE.SPEED);
  }

  /** 设置名字 */
  public setName(name: string): void {
    this.name = name;
  }

  /** 获取技能列表 */
  public getSkills(): ReadonlyArray<BattleSkill> {
    return [...this.skills];
  }

  /**
   * 添加技能
   * @param skill - 要添加的技能
   */
  public addSkill(skill: BattleSkill): void {
    if (!this.skills.some((s) => s.id === skill.id)) {
      this.skills.push(skill);
    }
  }

  /**
   * 移除技能
   * @param skillId - 要移除的技能ID
   * @returns 如果成功移除返回true，否则返回false
   */
  public removeSkill(skillId: string): boolean {
    const index = this.skills.findIndex((skill) => skill.id === skillId);
    if (index !== -1 && skillId !== NORMAL_ATTACK.id) {
      this.skills.splice(index, 1);
      return true;
    }
    return false;
  }

  public setBattleSkillAttributeValue(
    attributeKey: BattleSkillAttributeKey,
    value: number
  ) {
    this.battleSkillAttributes[attributeKey] = value;
  }

  public getBattleSkillAttributeValue(
    attributeKey: BattleSkillAttributeKey
  ): number {
    return this.battleSkillAttributes[attributeKey];
  }

  public getBattleSkillAttributes(): BattleSkillAttribute {
    return this.battleSkillAttributes;
  }

  public updateBattleSkillAttributes() {
    this.battleSkillAttributes = {
      [BATTLE_SKILL_ATTRIBUTE.ATTACK]: this.attributes.getAttributeValue(
        ATTRIBUTE_TYPE.ATTACK
      ),
      [BATTLE_SKILL_ATTRIBUTE.DEFENSE]: this.attributes.getAttributeValue(
        ATTRIBUTE_TYPE.DEFENSE
      ),
      [BATTLE_SKILL_ATTRIBUTE.SPEED]: this.attributes.getAttributeValue(
        ATTRIBUTE_TYPE.SPEED
      ),
      [BATTLE_SKILL_ATTRIBUTE.MAX_HEALTH]: this.attributes.getAttributeValue(
        ATTRIBUTE_TYPE.HEALTH
      ),
      [BATTLE_SKILL_ATTRIBUTE.CURRENT_HEALTH]: this.currentHealth,
    };
  }

  /**
   * 获取最后一次伤害来源
   * @returns 造成最后一次伤害的单位，如果没有则返回null
   */
  public getLastDamageSource(): BattleUnit | null {
    return this.lastDamageSource;
  }

  /**
   * 获取最后一次受到的伤害信息
   * @returns 伤害信息的只读副本，包含伤害详情和生命值变化
   */
  public getLastDamageInfo(): Readonly<typeof this.lastDamageTaken> {
    return this.lastDamageTaken ? { ...this.lastDamageTaken } : null;
  }

  /**
   * 检查单位是否存活
   * @returns 如果单位存活且生命值大于0返回true，否则返回false
   */
  public isAlive(): boolean {
    return this.isActive && this.currentHealth > 0;
  }

  /**
   * 设置单位激活状态
   * @param active - 是否激活单位
   */
  public setActive(active: boolean): void {
    this.isActive = active;
  }

  /**
   * 承受伤害
   * @param damage - 原始伤害值
   */
  public takeDamage(damage: number, skill: BattleSkill, source: BattleUnit) {
    /** 记录伤害来源和技能 */
    if (source) {
      this.lastDamageSource = source;
    }

    const previousHealth = this.currentHealth;
    this.currentHealth = Math.max(0, this.currentHealth - damage);

    this.lastDamageTaken = {
      amount: damage,
      source: source,
      timestamp: Date.now(),
      wasLethal: this.currentHealth === 0,
      previousHealth: previousHealth,
      currentHealth: this.currentHealth,
      healthLost: previousHealth - this.currentHealth,
      skill,
    };

    /** 检查是否触发基于生命值变化的效果 */
    this.checkHealthBasedEffects(previousHealth, this.currentHealth);

    /** 检查是否死亡 */
    if (this.currentHealth === 0) {
      this.setActive(false);
      if (source) {
        this.onDeathBySource(source, skill);
      }
    }
  }

  /**
   * 检查基于生命值变化的效果触发条件
   * @param previousHealth - 变化前的生命值
   * @param currentHealth - 当前生命值
   */
  private checkHealthBasedEffects(
    previousHealth: number,
    currentHealth: number
  ): void {
    const healthPercentage = currentHealth / this.maxHealth;
    const previousPercentage = previousHealth / this.maxHealth;

    // 生命值低于30%时触发低生命值效果
    if (previousPercentage > 0.3 && healthPercentage <= 0.3) {
      this.onLowHealth();
    }

    // 单次伤害超过最大生命值20%时触发重创效果
    const healthChange = previousHealth - currentHealth;
    if (healthChange > this.maxHealth * 0.2) {
      this.onSignificantDamage();
    }
  }

  /** 当生命值降到低水平时触发（低于30%） */
  private onLowHealth(): void {
    // 预留方法，用于触发低生命值效果
    // 例如：触发狂暴状态、自动治疗等
  }

  /** 当受到显著伤害时触发（单次伤害超过最大生命值20%） */
  private onSignificantDamage(): void {
    // 预留方法，用于触发大额伤害效果
    // 例如：触发护盾、反击等
  }

  /**
   * 当被特定来源杀死时的处理
   * @param killer - 击杀者单位
   * @param skill - 造成死亡的技能（可选）
   */
  private onDeathBySource(_killer: BattleUnit, _skill?: BattleSkill): void {
    // 预留方法，用于后续扩展死亡效果
    // 例如：击杀者获得经验值、触发连杀效果等
    // const skillInfo = skill ? `使用 ${skill.name}` : '';
  }

  /**
   * 治疗单位
   * @param amount - 治疗量
   * @returns 实际治疗量（受最大生命值限制）
   */
  public heal(amount: number): number {
    if (!this.isAlive()) return 0;

    const maxHeal = this.maxHealth - this.currentHealth;
    const actualHeal = Math.min(amount, maxHeal);
    this.currentHealth += actualHeal;

    return actualHeal;
  }

  /**
   * 获取单位状态快照
   * @returns 单位当前状态的只读快照
   */
  public getSnapshot() {
    return {
      id: this.id,
      name: this.name,
      side: this.side,
      currentHealth: this.currentHealth,
      maxHealth: this.maxHealth,
      attack: this.attack,
      defense: this.defense,
      speed: this.speed,
      isAlive: this.isAlive(),
      lastDamageSource: this.lastDamageSource?.id || null,
      skills: this.getSkills(),
    };
  }

  /** 根据敌人实例创建战斗单位 */
  public static createEnemy(enemy: Enemy, skills?: BattleSkill[]): BattleUnit {
    return new BattleUnit(
      `${enemy.id}_${uuidv4()}`,
      enemy.id,
      enemy.name,
      BATTLE_SIDE.ENEMY,
      enemy.attributes.calculateFinalAttributes(),
      skills
    );
  }

  /** 根据队友实例创建战斗单位 */
  public static createTeammate(
    teammate: Teammate,
    skills?: BattleSkill[]
  ): BattleUnit {
    return new BattleUnit(
      `${teammate.id}_${uuidv4()}`,
      teammate.id,
      teammate.name,
      BATTLE_SIDE.PLAYER,
      teammate.attributes.calculateFinalAttributes(),
      skills
    );
  }

  /** 根据玩家属性创建战斗单位 */
  public static createPlayer(
    playerAttributes: Attribute,
    skills?: BattleSkill[]
  ): BattleUnit {
    return new BattleUnit(
      'player',
      'player',
      '玩家',
      BATTLE_SIDE.PLAYER,
      playerAttributes,
      skills
    );
  }
}
